package raytracer.file;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.StringTokenizer;
import java.util.Vector;

public class OBJFileReader 
{
	@SuppressWarnings("resource")
	public static T_Mesh readFile(File f) throws Exception
	{
		T_Mesh mesh = new T_Mesh();
		
		Vector<float[]> verts = new Vector<float[]>();
		Vector<float[]> normals = new Vector<float[]>();
		Vector<int[]>   faces = new Vector<int[]>();
		Vector<int[]>   normalIndices = new Vector<int[]>();
		
		mesh.fileName = f.getName();
		
		FileReader fr;
		try 
		{
			fr = new FileReader(f);
			LineNumberReader br = new LineNumberReader(fr);
			
			String line;
			
			
			while ( (line = br.readLine()) != null)
			{
				
				if (line.startsWith("v "))
				{
					
					StringTokenizer st = new StringTokenizer(line);
					String token;
					
					float vert[] = new float[3];
					
					st.nextToken();
					int i = 0;
					
					while(st.hasMoreTokens())
					{
						token = st.nextToken();
						
						if (i > 2)
						{
							throw new Exception("wrong");
						}
						
						vert[i] = Float.parseFloat(token);
						i++;
					}
					
					verts.add(vert);						
				}
				
				if (line.startsWith("vn"))
				{
					
					StringTokenizer st = new StringTokenizer(line);
					String token;
					
					float normal[] = new float[3];
					
					st.nextToken();
					int i = 0;
					
					while(st.hasMoreTokens())
					{
						token = st.nextToken();
						
						if (i > 2)
						{
							throw new Exception("wrong");
						}
						
						normal[i] = Float.parseFloat(token);
						i++;
					}
					
					normals.add(normal);						
				}
				
				if (line.startsWith("f"))
				{
					
					StringTokenizer st = new StringTokenizer(line);
					String token;
					
					int face[] = new int[3];
					int normal[] = new int[3];
					
					st.nextToken();
					int i = 0;
					
					while(st.hasMoreTokens())
					{
						token = st.nextToken();
						
						StringTokenizer st2 = new StringTokenizer(token, "/");
						String token2;
						
						int j = 0;
						
						if (i > 2)
						{
							throw new Exception("no triangle mesh obj :(");
						}
						
						while(st2.hasMoreTokens())
						{
							token2 = st2.nextToken();
							
							if (j > 2)
							{
								throw new Exception("wrong");
							}
							
							if (j == 0)
							{
								face[i] = Integer.parseInt(token2) - 1;
								
							}
							
							if (j == 2)
							{
								normal[i] = Integer.parseInt(token2) - 1;
								
							}
							
							j++;
						}
						i++;
						
					}
					
					faces.add(face);
					normalIndices.add(normal);						
				}
				
				
			}
			
			
			// File read
					
			float sinA = (float) Math.sin(90 / 180.0f * Math.PI);
			float cosA = (float) Math.cos(90 / 180.0f * Math.PI);
			
			float sinB = (float) Math.sin(180 / 180.0f * Math.PI);
			float cosB = (float) Math.cos(180 / 180.0f * Math.PI);
			
			mesh.vertices = new float[verts.size()][3];
			mesh.vertexNormals = new float[verts.size()][3];
			for (int i = 0; i < verts.size(); i++)
			{
				float vert[] = verts.elementAt(i);
				mesh.vertices[i][0] = vert[0];
				//mesh.vertices[i][1] = vert[1];
				//mesh.vertices[i][2] = vert[2];
				
				mesh.vertices[i][1] = vert[1] * cosA + vert[2] * -sinA;
				mesh.vertices[i][2] = vert[1] * sinA + vert[2] * cosA;
				
				mesh.vertices[i][0] = mesh.vertices[i][0] * cosB + mesh.vertices[i][2] * sinB;
				mesh.vertices[i][2] = mesh.vertices[i][0] * -sinB + mesh.vertices[i][2] * cosB;
				
				//mesh.vertices[i][0] = mesh.vertices[i][0] * cosA + mesh.vertices[i][1] * -sinA;
				//mesh.vertices[i][1] = mesh.vertices[i][0] * sinA + mesh.vertices[i][1] * cosA;
				
			}
			
			int normI[];
			float normal[];
			
			mesh.triangles = new int[faces.size()][3];
			for (int i = 0; i < faces.size(); i++)
			{
				int face[] = faces.elementAt(i);
				
				mesh.triangles[i][0] = face[0];
				mesh.triangles[i][1] = face[1];
				mesh.triangles[i][2] = face[2];
				normI = normalIndices.elementAt(i);
				
				/*
				normal = normals.elementAt(normI[0]);
				mesh.vertexNormals[mesh.triangles[i][0]][0] = normal[0];
				mesh.vertexNormals[mesh.triangles[i][0]][1] = normal[1];
				mesh.vertexNormals[mesh.triangles[i][0]][2] = normal[2];
				
				normal = normals.elementAt(normI[1]);
				mesh.vertexNormals[mesh.triangles[i][1]][0] = normal[0];
				mesh.vertexNormals[mesh.triangles[i][1]][1] = normal[1];
				mesh.vertexNormals[mesh.triangles[i][1]][2] = normal[2];
				
				normal = normals.elementAt(normI[2]);
				mesh.vertexNormals[mesh.triangles[i][2]][0] = normal[0];
				mesh.vertexNormals[mesh.triangles[i][2]][1] = normal[1];
				mesh.vertexNormals[mesh.triangles[i][2]][2] = normal[2];
				*/
			}
			
			mesh.materials = new float[1][9];
			
			mesh.materials[0][0] = 0.15f;
			mesh.materials[0][1] = 0.15f;
			mesh.materials[0][2] = 0.15f;
			
			mesh.materials[0][3] = 0.0f;
			mesh.materials[0][4] = 0.8f;
			mesh.materials[0][5] = 0.0f;
			
			mesh.materials[0][6] = 0.8f;
			mesh.materials[0][7] = 0.8f;
			mesh.materials[0][8] = 0.8f;
			
			mesh.materialsN = new int[1];
			mesh.materialsN[0] = 10;
			
			mesh.verticesMat = new int[mesh.vertices.length];
			
			mesh.calcBoundingBox();
			
			System.out.println("min: " + mesh.min[0] + " / " + mesh.min[1] + " / " + mesh.min[2]);
			System.out.println("max: " + mesh.max[0] + " / " + mesh.max[1] + " / " + mesh.max[2]);
			
			mesh.fgp = 'p';
			
			return mesh;
			
				
			
		} 
		catch (FileNotFoundException e) 
		{
			e.printStackTrace();
		} 
		catch (IOException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		
		return null;
	}
	
	protected static String readLine(BufferedReader br) throws IOException {
		String result = br.readLine().trim();
		while(result.startsWith("#") || result.trim().isEmpty())
			result = br.readLine().trim();
		return result;
	}
}
